﻿# coding:utf-8

import datetime
import json
import re
import time
import urllib.parse

import requests

# import rail_cookie

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36',
}


def station_info():
    """
    获得所有站的信息
    :return:
    """
    url = 'https://www.12306.cn/index/script/core/common/station_name_v10012.js'
    response = requests.get(url)
    station_names = ''.join(re.findall('\'(.*?)\'', response.text))
    station_list = station_names.split('@')
    del station_list[0]
    return [i.split('|') for i in station_list]


station_list = station_info()

from_station_nm = input('请输入起点站名:')
to_station_nm = input('请输入终点站名:')
start_date = input('请输入出发日期:')
quote_from_station = urllib.parse.quote(from_station_nm)
quote_to_station = urllib.parse.quote(to_station_nm)


def query_ticket(from_station, to_station, start_date):
    # 获得查询结果
    for station in station_info():
        if station[1] == from_station:
            from_station = station[2]
        if station[1] == to_station:
            to_station = station[2]
            # print(from_station, to_station)
    response = requests.get(
        'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(
            start_date, from_station, to_station))
    all_result = response.text
    all_result = json.loads(all_result)['data']['result']
    ticket_result = [i.split('|') for i in all_result]
    for result in ticket_result:
        # print(result)
        if result[-9] == '':
            result[-9] = '无'
        if result[-12] == '':
            result[-12] = '无'
    return ticket_result


# print('备注\t\t编号\t\t车次\t起始站\t终点站\t途经(始)\t途径(终)\t耗时\t发车时间\t到达时间\t硬座\t无座')


# print('\t'.join(result[1:11]), '\t', result[-9], '\t', result[-12])
# result[-6] #商务座特等座
# result[-7] #一等座
# result[-8] #二等座
# result[-15] #软卧
# result[-9] #硬座
# result[-12] #无座


#


def check_user():
    url = "https://kyfw.12306.cn/otn/login/checkUser"
    data = {
        "_json_att": ""
    }
    resp = requests.post(url, data=data, headers=headers)
    # 反回一个验证通过信息
    if ''.join(re.findall('"flag":(.*?)}', resp.text)) == 'true':
        return True
    else:

        return False


def submit_order(ticket_result):
    data = {
        'train_date': start_date,
        'back_train_date': datetime.datetime.now().strftime('%Y-%m-%d'),
        'tour_flag': 'dc',
        'purpose_codes': 'ADULT',
        'query_from_station_name': quote_from_station,
        'query_to_station_name': quote_to_station,
        'undefined': '',
        'secretStr': ''
    }
    for i in ticket_result:
        if i[0] != '' and i[-9] != '无':
            data['secretStr'] = urllib.parse.unquote(i[0])

            global current_ticket
            current_ticket = i
            break
    url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
    resp = requests.post(url, data=data, headers=headers)


def initDc(headers):
    """获得token和key提交订单用"""
    data = {
        '_json_att': ''
    }
    key_all = requests.post('https://kyfw.12306.cn/otn/confirmPassenger/initDc', headers=headers, data=data)
    token = ''.join(re.findall("var globalRepeatSubmitToken = '(.*?)'", key_all.text))
    key = ''.join(re.findall("'key_check_isChange':'(.*?)'", key_all.text))
    return token, key


def check_order(headers, token, passengerTicketStr, oldPassengerStr):
    data = {
        'cancel_flag': '2',
        'bed_level_order_num': '000000000000000000000000000000',
        'passengerTicketStr': passengerTicketStr,
        'oldPassengerStr': oldPassengerStr,
        'tour_flag': 'dc',
        '_json_att': '',
        'randCode': '',
        'whatsSelect': '1',
        'REPEAT_SUBMIT_TOKEN': token,
    }
    info = requests.post('https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo', data=data, headers=headers)


def submit(key_check_isChange, token, passengerTicketStr, oldPassengerStr):
    """最终提交"""
    url = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue"
    data = {
        'passengerTicketStr': passengerTicketStr,
        'oldPassengerStr': oldPassengerStr,
        "randCode": "",
        "purpose_codes": "00",
        "key_check_isChange": key_check_isChange,
        "leftTicketStr": current_ticket[12],
        "train_location": current_ticket[15],
        "choose_seats": "",
        "seatDetailType": "000",
        "whatsSelect": "1",
        "roomType": "00",
        "dwAll": "N",
        "_json_att": "",
        "REPEAT_SUBMIT_TOKEN": token
    }
    response = requests.post(url, data=data, headers=headers)
    if ''.join(re.findall('"submitStatus":(.*?)}', response.text)) == 'true':
        return True
    return False


def get_passenger(REPEAT_SUBMIT_TOKEN):
    """
    :return: 返回一个乘客列表信息
    """
    print("获取乘车人信息.......")
    url = "https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs"
    data = {
        "_json_att": "",
        "REPEAT_SUBMIT_TOKEN": REPEAT_SUBMIT_TOKEN
    }
    resp = requests.post(url, data=data, headers=headers)
    if resp.status_code == requests.codes.ok:
        return json.loads(resp.text)['data']['normal_passengers']


def logo(info):
    # pass
    print(info)


def getQueueCount(trick_data, REPEAT_SUBMIT_TOKEN):
    """查看队列"""
    ts = time.mktime(time.strptime(start_date, "%Y-%m-%d"))
    s = time.ctime(ts)
    t = s[0:11] + s[20:] + " 00:00:00 GMT+0800 (中国标准时间)"
    print("检查余票...")
    url = "https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount"
    # 将字符串转化为需要的时间
    data = {
        # 时间
        "train_date": t,
        # 车次编号
        "train_no": trick_data[2],
        # 火车代码
        "stationTrainCode": trick_data[3],
        "seatType": "1",
        "fromStationTelecode": trick_data[6],
        "toStationTelecode": trick_data[7],
        "leftTicket": trick_data[12],
        "purpose_codes": "00",
        "train_location": trick_data[15],
        "_json_att": "",
        "REPEAT_SUBMIT_TOKEN": REPEAT_SUBMIT_TOKEN
    }
    resp = requests.post(url, data=data, headers=headers)
    if resp.status_code == requests.codes.ok:
        # 硬座类型
        ticket_count = re.findall('"ticket":"(.*?),(.*?)"', resp.text)[0]
        if ticket_count[0] == '':
            return False
        else:
            return True


cookie = input('请输入cookies')
headers['Cookie'] = cookie
print(headers['Cookie'])
# 检查是否登录
if check_user():
    token = initDc(headers)[0]
    all_passenger_info = get_passenger(token)
    if all_passenger_info == None:
        print('请添加联系人或者重新登录')
        exit()
    i = 0
    for info in all_passenger_info:
        print(i, end=' ')
        print(info)
        i += 1
    xz = input('请选择乘客，空格隔开，如0 1:').split(' ')
    # 构造购票信息字符串
    passengerTicketStr = []
    oldPassengerStr = ''
    for x in xz:
        x = int(x)
        passengerTicketStr.append(
            '1,0,1,' + all_passenger_info[x]['passenger_name'] + ',1,' + all_passenger_info[x][
                'passenger_id_no'] + ',' + \
            all_passenger_info[x]['mobile_no'] + ',N')
        oldPassengerStr += all_passenger_info[x]['passenger_name'] + ',1,' + all_passenger_info[x][
            'passenger_id_no'] + ',1_'
    passengerTicketStr = '_'.join(passengerTicketStr)
    while True:
        # 查票
        try:
            ticket_result = query_ticket(from_station_nm, to_station_nm, start_date)
            print(ticket_result)
            check_user()
            submit_order(ticket_result)
            token, key_check_isChange = initDc(headers)
            print(token, key_check_isChange)
            check_order(headers, token, passengerTicketStr, oldPassengerStr)
            print('当前的票', current_ticket)
            if getQueueCount(current_ticket, token):
                if submit(key_check_isChange, token, passengerTicketStr, oldPassengerStr):
                    print('购票成功')
                    exit()
        except Exception as e:
            print(e, '正在刷票中......')


else:
    print('登录失败')
